package com.op.parcel.manage.config.security.permission;

import com.op.parcel.manage.modules.sys.entity.Permission;
import com.op.parcel.manage.modules.sys.service.IPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 权限资源管理器
 * 为权限决断器提供支持
 *
 * @author xuan🐽
 */
@Slf4j
@Component
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	@Autowired
	private IPermissionService permissionService;

	private List<Permission> permissions = null;

	/**
	 * 判定用户请求的url是否在权限表中
	 * 如果在权限表中  {@link MyAccessDecisionManager#decide}
	 * 如果不在权限表中则放行
	 *
	 * @param o
	 * @return
	 * @throws IllegalArgumentException
	 */
	@Override
	public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
		if (permissions == null) {
			permissions = permissionService.getInterfacePermissions();
		}
		String url = ((FilterInvocation) o).getRequestUrl();
		//  remove parameters
		if (url.contains("?")) {
			url = url.substring(0, url.indexOf("?"));
		}
		PathMatcher pathMatcher = new AntPathMatcher();

		String finalUrl = url;
		List<ConfigAttribute> list = SecurityConfig.createList(permissions.stream()
			.filter(permission -> pathMatcher.match(permission.getPath(), finalUrl))
			.map(Permission::getTitle).collect(Collectors.toList()).toArray(new String[]{}));
		if (list != null && !list.isEmpty()) {
			return list;
		}

		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> aClass) {
		return true;
	}
}
